use std::cmp::Ordering;

use poker_lib::PokerCard;

use crate::turn::TurnHandPileState;

///计算每张可以出的牌的权重 x->rank或者某花色的张数 y->rank或者某花色的张数 z->是否空缺状态出的其他副花色
pub struct CardWeight {
    pub card: PokerCard,
    pub card_x: i16,
    pub card_y: i16,
    pub card_z: i16,
}

impl CardWeight {
    pub fn new(card: PokerCard, card_x: i16, card_y: i16, card_z: i16) -> Self {
        CardWeight {
            card,
            card_x,
            card_y,
            card_z,
        }
    }

    pub fn add_card_x(card_x: i16, card: &PokerCard, pile: &mut Vec<CardWeight>) {
        if let Some(playable_card_weight) = pile.iter_mut().find(|item| &item.card == card) {
            playable_card_weight.card_x += card_x;
        } else {
            pile.push(CardWeight::new(*card, card_x, 0, 0));
        }
    }

    pub fn add_card_y(card_y: i16, card: &PokerCard, pile: &mut Vec<CardWeight>) {
        if let Some(playable_card_weight) = pile.iter_mut().find(|item| &item.card == card) {
            playable_card_weight.card_y += card_y;
        } else {
            pile.push(CardWeight::new(*card, 0, card_y, 0));
        }
    }

    pub fn add_card_z(card_z: i16, card: &PokerCard, pile: &mut Vec<CardWeight>) {
        if let Some(playable_card_weight) = pile.iter_mut().find(|item| &item.card == card) {
            playable_card_weight.card_z += card_z;
        } else {
            pile.push(CardWeight::new(*card, 0, 0, card_z));
        }
    }
    pub fn add_lowest_card_item(card: &PokerCard, _card_weights: &mut Vec<CardWeight>) {
        _card_weights.push(CardWeight::new(*card, -100, 0, 0));
        _card_weights.push(CardWeight::new(*card, 0, -100, 0));
        _card_weights.push(CardWeight::new(*card, 0, 0, -100));
    }
    ///升序 添加黑桃权重 优先小主
    pub fn add_playable_spades_card_weight(
        _hand_pile: &TurnHandPileState,
        _card_weights: &mut Vec<CardWeight>,
    ) {
        for item in &_hand_pile.spades_pile {
            let card_x = 14 - item.get_number();
            CardWeight::add_card_x(card_x, item, _card_weights);
        }
    }

    pub fn add_playable_mid_card_weight(
        _hand_pile: &TurnHandPileState,
        _card_weights: &mut Vec<CardWeight>,
    ) {
        for item in &_hand_pile.playable_pile {
            if !item.is_trump_card()
                || _hand_pile.playable_pile.len() == _hand_pile.spades_pile.len()
            {
                let pile = _hand_pile.pile_suit_group.get_suit_pocker_cards(item.suit);
                let card_x = if _hand_pile.mid_cards.contains(item) {
                    item.get_number() as i16
                } else {
                    2
                };
                Self::add_card_x(card_x, item, _card_weights);
                let card_y = 13 - pile.len() as i16;
                Self::add_card_y(card_y, item, _card_weights);
                let card_z = 14 - item.get_number() as i16;
                Self::add_card_z(card_z, item, _card_weights);
            }
        }
    }

    pub fn add_playable_big_card_weight(
        _hand_pile: &TurnHandPileState,
        _card_weights: &mut Vec<CardWeight>,
    ) {
        for item in &_hand_pile.playable_pile {
            if !item.is_trump_card()
                || _hand_pile.playable_pile.len() == _hand_pile.spades_pile.len()
            {
                let pile = _hand_pile.pile_suit_group.get_suit_pocker_cards(item.suit);
                if _hand_pile.big_cards.contains(item) {
                    Self::add_card_x(item.get_number(), item, _card_weights);
                }
                Self::add_card_y(13 - pile.len() as i16, item, _card_weights);
                Self::add_card_z(14 - item.get_number(), item, _card_weights);
            }
        }
    }

    pub fn add_playable_card_weight(
        _hand_pile: &TurnHandPileState,
        _card_weights: &mut Vec<CardWeight>,
    ) {
        for item in &_hand_pile.playable_pile {
            // Vice suit or all spades case
            if !item.is_trump_card()
                || _hand_pile.playable_pile.len() == _hand_pile.spades_pile.len()
            {
                let pile = _hand_pile.pile_suit_group.get_suit_pocker_cards(item.suit);
                if _hand_pile.big_cards.contains(item) {
                    Self::add_card_x(item.get_number() + 100, item, _card_weights);
                } else if _hand_pile.mid_cards.contains(item) {
                    Self::add_card_x(item.get_number(), item, _card_weights);
                }
                Self::add_card_y(13 - pile.len() as i16, item, _card_weights);
                Self::add_card_z(14 - item.get_number() as i16, item, _card_weights);
            }
        }
    }
}

impl Ord for CardWeight {
    fn cmp(&self, other: &Self) -> Ordering {
        if self.card_x == other.card_x {
            if self.card_y == other.card_y {
                return other
                    .card_z
                    .partial_cmp(&self.card_z)
                    .unwrap_or(Ordering::Equal);
            }
            return other
                .card_y
                .partial_cmp(&self.card_y)
                .unwrap_or(Ordering::Equal);
        }
        other
            .card_x
            .partial_cmp(&self.card_x)
            .unwrap_or(Ordering::Equal)
    }
}

impl PartialOrd for CardWeight {
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        Some(self.cmp(other))
    }
}

impl PartialEq for CardWeight {
    fn eq(&self, other: &Self) -> bool {
        self.card == other.card && self.card_x == other.card_x&& self.card_y == other.card_y&&self.card_z == other.card_z
    }
}

impl Eq for CardWeight {
    
}
